package cn.amaake.magicplugin.satoken.Interceptor;

import cn.amaake.magicplugin.satoken.config.MagicApiSaTokenConfig;
import cn.amaake.magicplugin.satoken.interfaces.SatokenUserInterface;
import cn.amaake.magicplugin.satoken.model.SatokenUser;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.context.ApplicationContext;
import org.ssssssss.magicapi.core.context.MagicUser;
import org.ssssssss.magicapi.core.exception.MagicLoginException;
import org.ssssssss.magicapi.core.interceptor.Authorization;
import org.ssssssss.magicapi.core.interceptor.AuthorizationInterceptor;
import org.ssssssss.magicapi.core.model.Group;
import org.ssssssss.magicapi.core.model.MagicEntity;
import org.ssssssss.magicapi.core.servlet.MagicHttpServletRequest;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


public class CustomAuthorizationInterceptor implements AuthorizationInterceptor {

    private final MagicApiSaTokenConfig magicApiSaTokenConfig;

    private final ApplicationContext applicationContext;


    public CustomAuthorizationInterceptor(MagicApiSaTokenConfig magicApiSaTokenConfig,ApplicationContext applicationContext){
        this.magicApiSaTokenConfig = magicApiSaTokenConfig;
        this.applicationContext = applicationContext;
    }

    /**
     * 配置是否需要登录
     */
    @Override
    public boolean requireLogin() {
        return magicApiSaTokenConfig.isEnableLogin();
    }

    /**
     * 根据Token获取User
     */
    @Override
    public MagicUser getUserByToken(String token) throws MagicLoginException {
        String id = StpUtil.getLoginIdByToken(token).toString();

        if(id != null){
            SaSession saSession = StpUtil.getTokenSessionByToken(token);
            return saSession.getModel("satokenuser", SatokenUser.class);
        }
        throw new MagicLoginException("token无效");
    }

    @Override
    public MagicUser login(String username, String password) throws MagicLoginException {
        // 根据实际情况进行修改，如查询数据库。。

        Class<?>  aClass = applicationContext.getBean(SatokenUserInterface.class).getClass();
        SatokenUser satokenUser;
        try {
            Method method = aClass.getDeclaredMethod("getSatokenUser", String.class);
            satokenUser = (SatokenUser)method.invoke(applicationContext.getBean(SatokenUserInterface.class),username,password,null,false);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }

        if(satokenUser != null){
            // 登录成功后 构造MagicUser对象。
            String id = satokenUser.getId();
            StpUtil.login(id);
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            SaSession saSession = StpUtil.getTokenSession();
            satokenUser.setToken(tokenInfo.getTokenValue());
            saSession.set("satokenuser",satokenUser);
            return satokenUser;
        }
        throw new MagicLoginException("用户名或密码不正确");
    }


    /**
     * 是否拥有页面按钮的权限
     */
    @Override
    public boolean allowVisit(MagicUser magicUser, MagicHttpServletRequest request, Authorization authorization) {
        // Authorization.SAVE 保存
        // Authorization.DELETE 删除
        // Authorization.VIEW 查询
        // Authorization.LOCK 锁定
        // Authorization.UNLOCK 解锁
        // Authorization.DOWNLOAD 导出
        // Authorization.UPLOAD 上传
        // Authorization.PUSH 推送
        Class<?>  aClass = applicationContext.getBean(SatokenUserInterface.class).getClass();
        boolean boo;
        try {
            Method method = aClass.getDeclaredMethod("allowVisitPage", String.class);
            boo = (boolean)method.invoke(applicationContext.getBean(SatokenUserInterface.class),magicUser.getId(),request,authorization);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        return boo;
    }

    /**
     * 是否拥有对该接口的增删改权限
     * 此方法可以不重写，则走默认的 boolean allowVisit(MagicUser magicUser, HttpServletRequest request, Authorization authorization) 方法
     */
    @Override
    public boolean allowVisit(MagicUser magicUser, MagicHttpServletRequest request, Authorization authorization, MagicEntity entity) {
        // Authorization.SAVE 保存
        // Authorization.DELETE 删除
        // Authorization.VIEW 查询
        // Authorization.LOCK 锁定
        // Authorization.UNLOCK 解锁
        // 自行写逻辑判断是否拥有如果有，则返回true，反之为false
        Class<?>  aClass = applicationContext.getBean(SatokenUserInterface.class).getClass();
        boolean boo;
        try {
            Method method = aClass.getDeclaredMethod("allowVisitMagicEntity", String.class);
            boo = (boolean)method.invoke(applicationContext.getBean(SatokenUserInterface.class),magicUser.getId(),request,authorization,entity);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        return boo;
    }

    /**
     * 是否拥有对该分组的增删改权限
     * 此方法可以不重写，则走默认的 boolean allowVisit(MagicUser magicUser, HttpServletRequest request, Authorization authorization) 方法
     */
    @Override
    public boolean allowVisit(MagicUser magicUser, MagicHttpServletRequest request, Authorization authorization, Group group) {
        // Authorization.SAVE 保存
        // Authorization.DELETE 删除
        // Authorization.VIEW 查询
        // 自行写逻辑判断是否拥有如果有，则返回true，反之为false
        Class<?>  aClass = applicationContext.getBean(SatokenUserInterface.class).getClass();
        boolean boo;
        try {
            Method method = aClass.getDeclaredMethod("allowVisitGroup", String.class);
            boo = (boolean)method.invoke(applicationContext.getBean(SatokenUserInterface.class),magicUser.getId(),request,authorization,group);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        return boo;
    }



}
